package com.quan.mall.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.quan.commons.core.biz.support.MyBaseServiceImpl;
import com.quan.commons.core.exception.BizException;
import com.quan.commons.core.utils.PageUtils;
import com.quan.commons.core.utils.PasswordUtils;
import com.quan.commons.core.utils.RandomUitl;
import com.quan.mall.commons.vo.*;
import com.quan.mall.entity.*;
import com.quan.mall.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

import com.quan.mall.mapper.UmsMemberMapper;
import org.springframework.transaction.annotation.Transactional;


@Slf4j
@Service
public class UmsMemberServiceImpl extends MyBaseServiceImpl<UmsMemberMapper, UmsMember> implements UmsMemberService {

    @Autowired
	private UmsMemberMapper mapper;

    @Autowired
    private UmsMemberLevelService umsMemberLevelService;

    @Autowired
    private WmsAgentInfoService wmsAgentInfoService;

    @Autowired
    private UmsMemberReceiveAddressService umsMemberReceiveAddressService;

    @Autowired
    private FmsMemberWalletService fmsMemberWalletService;

    @Autowired
    private FmsMemberWithdrawService fmsMemberWithdrawService;

    @Autowired
    private FmsMemberCashFlowService fmsMemberCashFlowService;

    @Autowired
    private FmsMemberCommisionFreezeService fmsMemberCommisionFreezeService;

    @Autowired
    private OmsOrderService omsOrderService;

    @Autowired
    private OmsOrderGoodsService omsOrderGoodsService;

    @Autowired
    private UmsCouponService umsCouponService;

    @Autowired
    private UmsCouponMemberRelationService umsCouponMemberRelationService;

    @Override
    public boolean save(UmsMember entity) {

        if(super.hasExist("mobile", entity.getMobile(), UmsMember.class)) {
            throw new BizException("会员手机号已存在");
        }

        // 加密盐
        entity.setSecret(RandomUitl.uuid());
        // 默认密码：手机号后6位
        String password = StringUtils.isNotBlank(entity.getPassword()) ? entity.getPassword() : entity.getMobile().substring(5, 11);
        // 密码加密
        entity.setPassword(PasswordUtils.encodePassword(password, entity.getSecret()));

        // 我的邀请码
        entity.setCode(RandomUtil.randomNumbers(4));

        final UmsMemberLevel level = this.umsMemberLevelService.getById(entity.getLevelId());

        // 修改会员级别，同时修改类型
        entity.setType(level.getLevel());

        return super.save(entity);
    }

    @Transactional
    @Override
    public boolean saveMember(UmsMemberVo vo) {

        if(super.hasExist("mobile", vo.getMobile(), UmsMember.class)) {
            throw new BizException("会员手机号已存在");
        }

        // 加密盐
        vo.setSecret(RandomUitl.uuid());
        // 默认密码：手机号后6位
        String password = StringUtils.isNotBlank(vo.getPassword()) ? vo.getPassword() : vo.getMobile().substring(5, 11);
        // 密码加密
        vo.setPassword(PasswordUtils.encodePassword(password, vo.getSecret()));

        if(null != vo.getType() && vo.getType() == 5) { // 会员类型：代理商
            // 代理商无需设置会员级别
            vo.setLevelId(null);
        } else {
            // 会员类型
            vo.setType(1);

            // 我的邀请码
            vo.setCode(RandomUtil.randomNumbers(4));

            // 会员默认级别
            final UmsMemberLevel defaultLevel = this.umsMemberLevelService.getDefaultLevel();
            if(null != defaultLevel) {
                vo.setLevelId(defaultLevel.getId());
            }
        }


        // 判断是否有上级，有则绑定关系
        if (StringUtils.isNotBlank(vo.getRefereeCode())) {
            UmsMember um = this.getMemberByCode(vo.getRefereeCode());
            if (um != null) {
                vo.setRefereeMemberId(um.getId());
                vo.setRefereeMemberName(um.getNickname());
                vo.setRefereeMemberOpenId(um.getRefereeMemberOpenId());
            } else {
                throw new BizException("邀请码不存在");
            }
        }

        final boolean save = super.save(vo);

        // 初始化注册会员钱包
        FmsMemberWallet memberWallet = new FmsMemberWallet();
        memberWallet.setMemberId(vo.getId());
        memberWallet.setName(vo.getNickname());
        memberWallet.setPhone(vo.getMobile());
        this.fmsMemberWalletService.save(memberWallet);


        return save;
    }

    @Override
    public boolean updateById(UmsMember entity) {

        final UmsMemberLevel level = this.umsMemberLevelService.getById(entity.getLevelId());

        // 修改会员级别，同时修改类型
        entity.setType(level.getLevel());

        return super.updateById(entity);
    }

    @Override
    public List<UmsMemberVo> queryList(PageUtils pageUtils, UmsMemberVo vo) {
        QueryWrapper<UmsMember> queryWrapper = new QueryWrapper<UmsMember>(vo);

        List<UmsMember> list = super.list(pageUtils, queryWrapper);
        List<UmsMemberVo> collect = list.stream().map(item -> {
            UmsMemberVo bean = new UmsMemberVo();
            BeanUtils.copyProperties(item, bean);
            return bean;
        }).collect(Collectors.toList());

        return collect;
    }

    @Override
    public PageUtils queryPage(PageUtils pageUtils, UmsMemberVo vo) {
        QueryWrapper<UmsMember> queryWrapper = new QueryWrapper<UmsMember>(vo);

        if(StringUtils.isNotBlank(vo.getKeyword())) {
            queryWrapper.and(w -> {
                w.like("nickname", vo.getKeyword())
                .or().like("id", vo.getKeyword())
                .or().like("mobile", vo.getKeyword());
            });
        }

        final IPage<UmsMember> page = super.selectPage(pageUtils, queryWrapper);

        PageUtils ps = new PageUtils(page);

        final List<UmsMember> records = page.getRecords();

        final List<UmsMember> collect = records.stream().map((item) -> {
            UmsMemberVo bean = new UmsMemberVo();
            BeanUtils.copyProperties(item, bean);

            // 会员级别
            final UmsMemberLevel level = this.umsMemberLevelService.getById(item.getLevelId());
            if(null != level) {
                bean.setLevel(level);
            }

            // 代理商
            final WmsAgentInfo agentInfo = this.wmsAgentInfoService.getById(item.getAgentId());
            if(null != agentInfo) {
                bean.setAgent(agentInfo);
            }

            return bean;
        }).collect(Collectors.toList());

        ps.setRecords(collect);
        return ps;
    }

    @Override
    public UmsMemberVo register(UmsMemberVo vo) {
        UmsMember member = new UmsMember();
        BeanUtils.copyProperties(vo, member);

        // 会员默认级别
        final UmsMemberLevel defaultLevel = this.umsMemberLevelService.getDefaultLevel();
        if(null != defaultLevel) {
            member.setLevelId(defaultLevel.getId());
        }

        super.save(member);
        vo.setId(member.getId());

        return vo;
    }

    @Override
    public UmsMemberVo getMemberByOpenId(String openid) {
        final UmsMember member = super.getOne(new QueryWrapper<UmsMember>().eq("openid", openid));
        if(null != member) {
            UmsMemberVo vo = new UmsMemberVo();

            final UmsMemberLevel level = this.umsMemberLevelService.getById(member.getLevelId());
            vo.setLevel(level);

            BeanUtils.copyProperties(member, vo);
            return vo;
        } else {
            return null;
        }

    }

    @Override
    public void changeStatus(Long id, Integer status) {
        UpdateWrapper<UmsMember> updateWrapper = new UpdateWrapper<UmsMember>();
        updateWrapper.eq("id", id);
        updateWrapper.set("status", status);
        super.update(updateWrapper);
    }

    @Override
    public UmsMember getMemberByMobile(String mobile) {
        final UmsMember member = super.getOne(new QueryWrapper<UmsMember>().eq("mobile", mobile));
        if(null != member) {
            UmsMemberVo vo = new UmsMemberVo();

            final UmsMemberLevel level = this.umsMemberLevelService.getById(member.getLevelId());
            vo.setLevel(level);

            BeanUtils.copyProperties(member, vo);
            return vo;
        } else {
            return null;
        }
    }

    @Override
    public UmsMember getMemberByCode(String code) {
        final UmsMember member = super.getOne(new QueryWrapper<UmsMember>().eq("code", code));
        if(null != member) {

            return member;
        } else {
            return null;
        }
    }

    @Override
    public UmsMemberVo upgradeMember(Long memberId, Long levelId) {
        UmsMemberVo memberVo = new UmsMemberVo();

        final UmsMember member = super.getById(memberId);

        // 获取升级的级别
        final UmsMemberLevel level = this.umsMemberLevelService.getById(levelId);

        if(null != level) {

            // 如果会员当前的级别与要升级的级别一致，这是续费，从当前的有效期再加上一年
            if(member.getLevelId() == levelId) {
                // 当前会员级别的有效期+1年
                member.setExpire(member.getExpire().plusYears(1).minusDays(1));
            } else {
                // 当前日期的一年后
                member.setExpire(LocalDate.now().plusYears(1).minusDays(1));
            }

            // 修改会员级别
            member.setLevelId(level.getId());
            // 会员类型
            member.setType(level.getLevel());

            member.setUpgradeCount((null != member.getUpgradeCount()?member.getUpgradeCount()+1:1));
            super.updateById(member);

        }

        BeanUtils.copyProperties(member, memberVo);

        return memberVo;
    }

    @Override
    public UmsMemberVo getMyCecommend(Long memberId) {
        UmsMemberVo vo = new UmsMemberVo();

        List<FmsMemberCashFlow> fmsMemberCashFlows = this.fmsMemberCashFlowService.getMemberCashFlowOnCecommend(memberId);

        if(null != fmsMemberCashFlows && fmsMemberCashFlows.size() > 0) {
            vo.setCecommendCount(fmsMemberCashFlows.size());

            // 计算邀请会员升级所获得的提成，总金额
            final BigDecimal reduce = fmsMemberCashFlows.stream().map(FmsMemberCashFlow::getTransactionAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setCecommendAmount(reduce);

            vo.setCecommendMemberList(fmsMemberCashFlows);

        }
        return vo;
    }

    @Override
    public UmsMemberVo getMyWallter(Long memberId) {
        UmsMemberVo vo = new UmsMemberVo();

        // 钱包
        final FmsMemberWallet wallet = this.fmsMemberWalletService.getMemberWallter(memberId);
        vo.setAmount(wallet.getAmount());

        // 获取会员冻结金额的记录
        List<FmsMemberCommisionFreeze> freezes = this.fmsMemberCommisionFreezeService.getMemberFreezeList(memberId);
        final BigDecimal totalFreezeAmoount = freezes.stream().map(FmsMemberCommisionFreeze::getFreezeAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        vo.setFreezeAmount(totalFreezeAmoount);

        // 获取累计收入
        List<FmsMemberCashFlow> cashFlows = this.fmsMemberCashFlowService.getMemberIncome(memberId);
        final BigDecimal reduceIncome = cashFlows.stream().map(FmsMemberCashFlow::getTransactionAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        vo.setTotalAmount(reduceIncome);

        return vo;
    }

    @Override
    public PageUtils getMyDistribution(PageUtils pageUtils, OmsOrderVo vo) {

        final PageUtils page = this.omsOrderService.queryPage(pageUtils, vo);

        final List<OmsOrderVo> records = (List<OmsOrderVo>) page.getRecords();
        records.stream().map(item -> {

            FmsMemberCashFlow cashFlow = this.fmsMemberCashFlowService.getOrderDistributionCommission(vo.getRefereeMemberId(), item.getOrderSn());

            System.out.println(cashFlow);
            if(null != cashFlow) {
                // 订单的分销佣金
                item.setDistributionCommission(cashFlow.getTransactionAmount());
            }

            return item;
        }).collect(Collectors.toList());


        return page;
    }

    @Override
    public void addCoupon(UmsMemberVo vo) {
        for (UmsCouponVo couponVo : vo.getCouponVos()) {
            final Long id = couponVo.getId();
            final Integer num = couponVo.getNum();

            for (Integer i = 0; i < num; i++) {
                UmsCouponMemberRelation umsCouponMemberRelation = new UmsCouponMemberRelation();
                umsCouponMemberRelation.setMemberId(vo.getId());
                umsCouponMemberRelation.setCouponId(id);

                this.umsCouponMemberRelationService.save(umsCouponMemberRelation);
            }
        }
    }

    @Override
    public List<UmsMemberCouponsVo> getUserCoupons(Long memberId) {
        List<UmsMemberCouponsVo> couponsVos = new ArrayList<UmsMemberCouponsVo>();

        final List<UmsCouponMemberRelation> relations = this.umsCouponMemberRelationService.list(new QueryWrapper<UmsCouponMemberRelation>().eq("member_id", memberId));

        for (UmsCouponMemberRelation relation : relations) {
            UmsMemberCouponsVo vo = new UmsMemberCouponsVo();
            vo.setUmsCouponMemberRelation(relation);

            final UmsCoupon coupon = this.umsCouponService.getById(relation.getCouponId());
            vo.setUmsCoupon(coupon);

            couponsVos.add(vo);
        }


        return couponsVos;
    }

}